package com.atguigu.dao;

import com.atguigu.constants.Constants;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.CompareFilter;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.filter.SubstringComparator;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

/*
        1 发布微博
        2 删除微博
        3 关注用户
        4 取关用户
        5 获取用户微博详情
        6 获取用户的初始化页面
     */
public class HbaseDao {
        //1 发布微博    参数(用户名id，文本内容)
        public static void publishWeiBo(String uid,String content) throws IOException {
            //1 获取connection对象
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
            //第一部分：操作微博内容表
            //1 拿到微博内容表对象
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            //2 获取当前时间戳
            long timestamps = System.currentTimeMillis();
            //3 获取rowKey
            String rowKey=uid+"_"+timestamps;
            //4 创建put对象
            Put contPut = new Put(Bytes.toBytes(rowKey));
            //5 给put对象赋值(列族，列，信息内容)
            contPut.addColumn(Bytes.toBytes(Constants.CONTENT_TABLE_CF),Bytes.toBytes("content"),Bytes.toBytes(content));
            //6 执行插入数据的操作
            contTable.put(contPut);

            //第二部分：操作微博收件箱表
            //1 获取用户关系表对象
            Table relationTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            //2 获取当前微博发布人的fan列族信息
            Get get = new Get(Bytes.toBytes(uid));
            get.addFamily(Bytes.toBytes(Constants.RELATION_TABLE_CF2));
            Result result = relationTable.get(get);
            //3 创建一个集合用于存放微博内容表的put对象
            ArrayList<Put> inboxPuts = new ArrayList<Put>();
            //4 遍历粉丝
            for (Cell cell: result.rawCells()) {    //只要进入了遍历，那么说明集合存在，有粉丝
                //5 要的列信息，构建微博收件箱表的put对象
                Put inboxPut = new Put(CellUtil.cloneQualifier(cell));
                //6 给收件箱的put对象赋值（列族，用户id，用户微博内容主键）
                inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF),Bytes.toBytes(uid),Bytes.toBytes(rowKey));
                //7 将收件箱表的put对象存入集合
                inboxPuts.add(inboxPut);
            }
            //8 判断是否存在粉丝
            if (inboxPuts.size()>0){
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                //执行收件箱表插入操作
                inboxTable.put(inboxPuts);
                inboxTable.close();
            }
            relationTable.close();
            contTable.close();
            connection.close();
        }

        //2 关注用户
        public static void addAttends(String uid,String... attends) throws IOException {
            if (attends.length<=0){
                System.out.println("请选择待关注的人");
            }
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
            //第一部分：操作用户的关系表
            Table relationTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            //创建一个集合用户用于存放用户关系表的put对象
            ArrayList<Put> relationPuts = new ArrayList<Put>();
            //创建操作者的put对象
            Put uidPut = new Put(Bytes.toBytes(uid));
            //循环创建被关注着的put对象
            for (String attend:attends) {
                //给操作者的put对象赋值
                uidPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF),Bytes.toBytes(attend),Bytes.toBytes(attend));
                //创建被关注者的put对象
                Put attendPut = new Put(Bytes.toBytes(attend));
                //给被关注者的put对象进行赋值
                attendPut.addColumn(Bytes.toBytes(Constants.RELATION_TABLE_CF2),Bytes.toBytes(uid),Bytes.toBytes(uid));
            }
            relationPuts.add(uidPut);
            relationTable.put(relationPuts);

            //第二部分：操作收件箱表
            //1 获取微博内容表的对象
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            //2 创建收件箱表的put对象
            Put inboxPut = new Put(Bytes.toBytes(uid));
            //3 循环attends，获取每个被关注者的近期发布的微博
            for (String attend : attends) {
                //4 获取当前被关乎着的近期发布的微博（scan）->集合
                Scan scan = new Scan(Bytes.toBytes(attend + "_"), Bytes.toBytes(attend + "|"));
                ResultScanner scanner = contTable.getScanner(scan);
                //定义时间戳，对数据时间戳进行控制
                long ts=System.currentTimeMillis();
                //5 地回去的值进行遍历
                for (Result result : scanner) {
                    //6 给收件箱表的put对象进行赋值
                    // （此时出现了问题：
                    // 1 先发的微博，先展示出来，为了实现找到最近的三条微博，对时间戳进行翻转，999~对事件戳相减
                    // 2 进行插入的时候，会对该条记录进行数据的时间戳插入，导致插入的时间是一样的，读取的时候就只能读取其中的一条数据。
                    inboxPut.addColumn(Bytes.toBytes(Constants.INBOX_TABLE_CF),Bytes.toBytes(attend),ts++,result.getRow());
                }
            }
            //判断当前put对象是否为空
            if (!inboxPut.isEmpty()){
                //获取收件箱表对象
                Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
                //插入数据
                inboxTable.put(inboxPut);
                //关闭连接
                inboxTable.close();
            }
            //关闭资源
            relationTable.close();
            connection.close();
        }
        //取消关注
        public static void deleteAttends(String uid,String... dels) throws IOException {
            if (dels.length<=0){
                System.out.println("请添加待取关的用户");
                return;
            }
            //获取connection对象
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
            //第一部分：用户关系表
            //1 获取用户关系表对象
            Table relationTable = connection.getTable(TableName.valueOf(Constants.RELATION_TABLE));
            //2 创建一个结合，用于存放用户关系表的delete对象
            ArrayList<Delete> relationDeletes = new ArrayList<Delete>();
            //3 创建操作者的delete对象
            Delete uidDelete = new Delete(Bytes.toBytes(uid));
            //4 循环创建被取关者的delete对象
            for (String del : dels) {
                //5 给操作者的delete对象赋值
                uidDelete.addColumns(Bytes.toBytes(Constants.RELATION_TABLE_CF),Bytes.toBytes(del));
                //6 创建被取关者的delete对象
                Delete delDelete = new Delete(Bytes.toBytes(del));
                //7 给被取关者添加值
                delDelete.addColumns(Bytes.toBytes(Constants.RELATION_TABLE_CF2),Bytes.toBytes(uid));
                //8 将被取关者的delete对象添加至集合
                relationDeletes.add(delDelete);
            }
            //9将操作者的delete对象添加至集合
            relationDeletes.add(uidDelete);
            //10执行用户关系表的删除操作
            relationTable.delete(relationDeletes);
            //第二部分：收件箱表
            //1 获取收件箱表对象
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
            //2 创建操作者的delete对象
            Delete inboxDelete = new Delete(Bytes.toBytes(uid));
            //3 给操作者的delete对象进行赋值
            for (String del : dels) {
                inboxDelete.addColumns(Bytes.toBytes(Constants.INBOX_TABLE_CF),Bytes.toBytes(del));
            }
            //4 执行收件箱表的删除操作
            inboxTable.delete(inboxDelete);
            //5 关闭资源
            inboxTable.close();
            connection.close();
        }

        //初始化某个用户微博的初始化页面
        public static void getInit(String uid) throws IOException {
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
            //获取收件箱表对象
            Table inboxTable = connection.getTable(TableName.valueOf(Constants.INBOX_TABLE));
            //获取微博内容表对象
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            //创建收件箱表get对象，应获取数据（设置最大的版本）
            Get inboxGet = new Get(Bytes.toBytes(uid));
            inboxGet.setMaxVersions(3);
            Result result = inboxTable.get(inboxGet);
            //遍历获取的数据
            for (Cell cell : result.rawCells()) {
                //创建微博内容表对象
                Get contGet= new Get(CellUtil.cloneValue(cell));
                //获取该get对象的数据内容
                Result contResult1 = contTable.get(contGet);
                //解析内容并打印
                for (Cell contCell: contResult1.rawCells()) {
                    System.out.println("RK:"+Bytes.toString(CellUtil.cloneRow(contCell))
                                    +",CF:"+Bytes.toString(CellUtil.cloneFamily(contCell))
                                    +",CN:"+Bytes.toString(CellUtil.cloneQualifier(contCell))
                                    +",value:"+Bytes.toString(CellUtil.cloneValue(contCell)));
                }

            }
            //关闭资源
            inboxTable.close();
            contTable.close();
            connection.close();
        }

        //获取某个人的全部的微博详情(简化版，仅展示所需要展示的那个人的id)
        //此处扩展一个内容：过滤器
        public static void getWeiBo(String uid) throws IOException {
            //1 获取Connection链接
            Connection connection = ConnectionFactory.createConnection(Constants.CONFIGURATION);
            //2 获取微博内容表对象
            Table contTable = connection.getTable(TableName.valueOf(Constants.CONTENT_TABLE));
            //3 获取scanner对象
            Scan scan = new Scan();
            //构建过滤器对象.参数：(比较规则，比较的对象)-->将rowkey单独的拿出来，然后查看是否可以截取出这样的"uid_"字符串
            RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator(uid+"_"));
            scan.setFilter(rowFilter);
            //4 获取表数据
            ResultScanner resultScanner = contTable.getScanner(scan);
            //5 解析数据并打印
            for (Result result : resultScanner) {
                for (Cell cell : result.rawCells()) {
                    System.out.println("RK:"+Bytes.toString(CellUtil.cloneRow(cell))
                            +",CF:"+Bytes.toString(CellUtil.cloneFamily(cell))
                            +",CN:"+Bytes.toString(CellUtil.cloneQualifier(cell))
                            +",value:"+Bytes.toString(CellUtil.cloneValue(cell)));
                }
            }
            contTable.close();
            connection.close();



        }



}
